package com.bridge.client.bridgedynamcclient.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.util.ParameterizedTypeImpl;
import com.bridge.client.bridgedynamcclient.bean.vo.resp.BaseResp;
import com.bridge.client.bridgedynamcclient.consts.Const;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public class HttpUtil {
    public static final String MEDIA_TYPE_MULTIPART = "multipart/form-data;charset=utf-8";
    public static final String MEDIA_TYPE_TEXT = "text/plain;charset=utf-8";

    /**
     * 通过httpClient上传文件
     * @param url--服务器地址
     * @param file---文件
     * @param params---其他参数
     * @return 结果字符串
     */
    public static String uploadFile(String url, File file, Map<String, String> params, Map<String, String> headMap) {
        try( CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(url);
            //HttpMultipartMode.RFC6532参数的设定是为避免文件名为中文时乱码
            MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
            builder.setCharset(StandardCharsets.UTF_8);
            if(headMap!=null){
                Set<String> keys= headMap.keySet();
                for (String queryString:keys){
                    httpPost.addHeader(queryString, headMap.get(queryString));//其余参数，可自定义
                }
            }
            String[] fileName=file.getName().split("\\.");
            builder.addBinaryBody("file", file, ContentType.parse(MEDIA_TYPE_MULTIPART), fileName[0]+"/"+fileName[1]);// 文件流
            if(params!=null){
                Set<String> keys= params.keySet();
                for (String queryString:keys){
                    if(!StringUtil.isEmpty(params.get(queryString))){
                        builder.addTextBody(queryString, params.get(queryString),ContentType.parse(MEDIA_TYPE_TEXT));//其余参数，可自定义
                    }
                }
            }
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            CloseableHttpResponse response = httpClient.execute(httpPost);// 执行提交
            String result = EntityUtils.toString(response.getEntity());
            System.out.println("uploadFile 请求完成,result:==>"+result);
            return result;
        }catch (Exception e){
            System.out.println(e);
            return null;
        }
    }



    public static String postBody(String url, Map<String, Object> params, Map<String, String> headMap) {
        if (params == null) {
            params = new HashMap<>();
        }
        if (headMap == null) {
            headMap = new HashMap<>();
        }
        if (!headMap.containsKey("Content-Type")) {
            headMap.put("Content-Type", "application/json; charset=UTF-8");
        }
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(url);

            JSONObject json = new JSONObject();
            generateParam(json, params);

            StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");
            httpPost.setEntity(stringEntity);

            Set<String> keys = headMap.keySet();
            for (String queryString : keys) {
                httpPost.addHeader(queryString, headMap.get(queryString));//其余参数，可自定义
            }

            System.out.println("postBodyParam 开始请求, param:==>"+json.toString());
            HttpResponse response = httpClient.execute(httpPost);
            String result = EntityUtils.toString(response.getEntity());
            System.out.println("postBodyParam 请求完成,result:==>"+result);
            return result;
        } catch (Exception e) {
            System.out.println(e);
            return null;
        }

    }

    private static void generateParam(JSONObject json, Map<String, Object> params) {
        if (params != null) {
            Set<String> keys = params.keySet();
            for (String key : keys) {
                Object value = params.get(key);
                if (Objects.nonNull(value)) {
                    if (value instanceof Map<?, ?>) {
                        JSONObject innerJson = new JSONObject();
                        generateParam(innerJson, (Map<String, Object>) value);
                        json.put(key, innerJson);
                    } else {
                        json.put(key, value);
                    }

                }
            }
        }
    }


    public static <T> T postBodyProxy(String url, Map<String, Object> params, Class<T> clazz){

        String result = postBody(url, params, null);
        if(StringUtil.isEmpty(result)){
            return null;
        }
        return JSON.parseObject(result,clazz);
    }

    public static <T> T uploadProxy(String url, File file,Map<String, String> params, Class<T> clazz){

        String result = uploadFile(url,file, params, null);
        if(StringUtil.isEmpty(result)){
            return null;
        }
        return JSON.parseObject(result,clazz);
    }

    public static <T>  BaseResp<T> postBodyProxyBaseResp(String url, Map<String, Object> params,TypeReference<T> typeInput){

        String result = postBody(url, params, null);
        if(StringUtil.isEmpty(result)){
            return null;
        }
        //在此处偷梁换柱（所谓的动态构造其实就一句话）
        TypeReference<BaseResp<T>> resultType = new TypeReference<BaseResp<T>>() {
            @Override
            public Type getType() {
                //在外层再包一层Result，就是所谓的动态构造，是不是很简单！！！
                return new ParameterizedTypeImpl(new Type[]{typeInput.getType()},null, BaseResp.class);
            }
        };
        return JSON.parseObject(result, resultType);
    }
}
